/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(unused_assignments, clippy::eq_op, unused_mut)]

use crate::common::*;

extern "C" {
    fn strtol(_: *const libc::c_char, _: *mut *mut libc::c_char, _: libc::c_int) -> libc::c_long;
    fn __ctype_tolower_loc() -> *mut *const __int32_t;
    fn __errno_location() -> *mut libc::c_int;
    fn sudo_debug_enter_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
    );
    fn sudo_debug_exit_int_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
        ret: libc::c_int,
    );
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
}
#[inline]
unsafe extern "C" fn tolower(mut __c: libc::c_int) -> libc::c_int {
    if __c >= -(128 as libc::c_int) && __c < 256 as libc::c_int {
        *(*__ctype_tolower_loc()).offset(__c as isize)
    } else {
        __c
    }
}

/*
 * Parse a command timeout in sudoers in the format 1d2h3m4s
 * (days, hours, minutes, seconds) or a number of seconds with no suffix.
 * Returns the number of seconds or -1 on error.
 */
#[no_mangle]
pub fn parse_timeout(mut timestr: *const libc::c_char) -> libc::c_int {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());
    }

    unsafe {
        let suffixes: [libc::c_char; 5] =
            *::core::mem::transmute::<&[u8; 5], &[libc::c_char; 5]>(b"dhms\0");
        let mut cp: *const libc::c_char = timestr;
        let mut timeout: libc::c_int = 0 as libc::c_int;
        let mut idx: libc::c_int = 0 as libc::c_int;
        loop {
            let mut ep: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
            let mut ch: libc::c_char = 0;
            let mut l: libc::c_long = 0;

            /* Parse number, must be present and positive. */
            *__errno_location() = 0 as libc::c_int;
            l = strtol(cp, &mut ep, 10 as libc::c_int);
            if ep == cp as *mut libc::c_char {
                /* missing timeout */
                *__errno_location() = EINVAL;
                debug_return_int!(-1);
            }
            if *__errno_location() == ERANGE || !(0..=0x7fffffff).contains(&l) {
                *__errno_location() = ERANGE;
                debug_return_int!(-1);
            }

            /* Find a matching suffix or return an error. */
            if *ep as libc::c_int != '\0' as i32 {
                ch = ({
                    let mut __res: libc::c_int = 0;
                    if ::core::mem::size_of::<libc::c_uchar>() as libc::c_ulong
                        > 1 as libc::c_int as libc::c_ulong
                    {
                        if 0 != 0 {
                            let fresh0 = ep;
                            ep = ep.offset(1);
                            let mut __c: libc::c_int = *fresh0 as libc::c_uchar as libc::c_int;
                            __res = if __c < -(128 as libc::c_int) || __c > 255 as libc::c_int {
                                __c
                            } else {
                                *(*__ctype_tolower_loc()).offset(__c as isize)
                            };
                        } else {
                            let fresh1 = ep;
                            ep = ep.offset(1);
                            __res = tolower(*fresh1 as libc::c_uchar as libc::c_int);
                        }
                    } else {
                        let fresh2 = ep;
                        ep = ep.offset(1);
                        __res = *(*__ctype_tolower_loc())
                            .offset(*fresh2 as libc::c_uchar as libc::c_int as isize);
                    }
                    __res
                }) as libc::c_char;

                while suffixes[idx as usize] as libc::c_int != ch as libc::c_int {
                    if suffixes[idx as usize] as libc::c_int == '\0' as i32 {
                        /* parse error */
                        *__errno_location() = EINVAL;
                        debug_return_int!(-1);
                    }
                    idx += 1;
                }

                /* Apply suffix. */
                match ch as u8 as char {
                    'd' => {
                        if l > (INT_MAX!() / (24 * 60 * 60)) {
                            *__errno_location() = ERANGE;
                            debug_return_int!(-1);
                        }
                        l *= 24 * 60 * 60;
                    }
                    'h' => {
                        if l > (INT_MAX!() / (60 * 60)) {
                            *__errno_location() = ERANGE;
                            debug_return_int!(-1);
                        }
                        l *= 60 * 60;
                    }
                    'm' => {
                        if l > (INT_MAX!() / 60) as libc::c_long {
                            *__errno_location() = ERANGE;
                            debug_return_int!(-1);
                        }
                        l *= 60;
                    }
                    _ => {}
                }
                if l > (INT_MAX!() - timeout) as libc::c_long {
                    *__errno_location() = ERANGE;
                    debug_return_int!(-1);
                }
            }
            cp = ep;
            timeout = (timeout as libc::c_long + l) as libc::c_int;
            if *cp as libc::c_int == '\0' as i32 {
                break;
            }
        }

        debug_return_int!(timeout);
    } //unsafe

    //执行不到下面的代码
    // overflow:
    // *__errno_location() = ERANGE;
    // debug_return_int!(-1);
}
